package com.yonyou.pmclouds.workflow.service;

import com.yonyou.pmclouds.basecom.entity.SuperVO;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.util.BeanHelper;
import com.yonyou.pmclouds.billtype.entity.BillTypeVO;
import com.yonyou.pmclouds.billtype.rmiitf.BillTypeQuery;
import com.yonyou.pmclouds.businessobject.entity.BoAttrsVO;
import com.yonyou.pmclouds.businessobject.util.BusinessObjectConfig;
import com.yonyou.pmclouds.businessobject.util.BusinessObjectConsts;
import com.yonyou.pmclouds.project.entity.ProjectVO;
import com.yonyou.pmclouds.project.rmiitf.ProjectSimpleQuery;
import com.yonyou.pmclouds.workflow.service.rmiitf.IProcessVariableExtendService;
import com.yonyou.pmclouds.workflow.util.BillFieldNameFormatCoverUtil;
import com.yonyou.pmclouds.workflow.util.DateCovertUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import yonyou.bpm.rest.request.RestVariable;

import java.util.*;

/**
 *  将业务VO转换为流程变量，用于分支节点条件判断
 *  @author zhangzhonghao
 */

@Component
@Slf4j
public class ProcessVariableProcessor {

    private static final String FIELD_TYPE_CHAR = "char";

    private static final String FIELD_TYPE_VARCHAR = "varchar";

    private static final String FIELD_TYPE_DATETIME = "datetime";

    private static final String FIELD_TYPE_BYTE = "byte";

    private static final String FIELD_TYPE_INT = "int";

    private static final String FIELD_TYPE_INTEGER = "Integer";

    private static final String FIELD_TYPE_TINYINT = "tinyint";

    private static BillTypeQuery billTypeQuery;

    private static ProjectSimpleQuery projectSimpleQuery;

    private static Map<String, IProcessVariableExtendService> variableExtendServiceMap = new HashMap<>();

    public static List<RestVariable> getVariableList(SuperVO buziVO) throws BusinessException {

        String billType = (String)BeanHelper.getProperty(buziVO, BillFieldNameFormatCoverUtil.getBillTypeFieldName(buziVO));

        // 统一将项目编码转化为项目名称
        String pkProject = (String)BeanHelper.getProperty(buziVO, BillFieldNameFormatCoverUtil.getPkProjectFieldName(buziVO));

        ProjectVO projectVO = projectSimpleQuery.queryProject(pkProject);
        if(projectVO != null) {
            BeanHelper.setProperty(buziVO, BillFieldNameFormatCoverUtil.getProjectNameFieldName(buziVO), projectVO.getSname());
            BeanHelper.setProperty(buziVO, BillFieldNameFormatCoverUtil.getProjectCodeFieldName(buziVO), projectVO.getScode());
        }

        extendVariable(billType, buziVO);

        if(StringUtils.isNotEmpty(billType)) {
            // 根据单据类型获取配置文件名称
            BillTypeVO billTypeVO = billTypeQuery.queryBillByType(billType, BillTypeVO.DATA_USAGE_APPROVAL);
            String tableName = billTypeVO.getTableName();
            // 获取表单字段
            List<BoAttrsVO> attrsVOS = getAttributeVOs(tableName);
            // 将字段类型转为变量支持的类型
            filterFieldType(attrsVOS);
            List<RestVariable> variableList = new ArrayList<>();
            for(BoAttrsVO boAttrsVO : attrsVOS) {
                RestVariable procVariable = new RestVariable();
                procVariable.setName(boAttrsVO.getCode());
                // 字段可选项配置不为空，则将字典项由编码转为描述
                if(boAttrsVO.getFieldOptionMap() != null) {
                    String value = String.valueOf(BeanHelper.getProperty(buziVO, boAttrsVO.getCode()));
                    if(value != null) {
                        procVariable.setValue(boAttrsVO.getFieldOptionMap().get(value));
                        procVariable.setType(RestVariable.STRING_VARIABLE_TYPE);
                    }
                }else {
                    // 如果是时间类型字段，value值需要传UTC时间格式，否则云审批会报Converter can only convert string to date
                    if(RestVariable.DATE_VARIABLE_TYPE.equalsIgnoreCase(boAttrsVO.getFieldtype())) {
                        Date date = (Date) BeanHelper.getProperty(buziVO, boAttrsVO.getCode());
                        procVariable.setValue(DateCovertUtil.covertDateToUTC(date));
                    }else if(RestVariable.DOUBLE_VARIABLE_TYPE.equalsIgnoreCase(boAttrsVO.getFieldtype())){
                        procVariable.setValue(BeanHelper.getProperty(buziVO, boAttrsVO.getCode()) == null ? 0d : BeanHelper.getProperty(buziVO, boAttrsVO.getCode()));
                    }else if(RestVariable.STRING_VARIABLE_TYPE.equalsIgnoreCase(boAttrsVO.getFieldtype()))
                    {
                        procVariable.setValue(BeanHelper.getProperty(buziVO, boAttrsVO.getCode()) == null ? "":BeanHelper.getProperty(buziVO, boAttrsVO.getCode()));
                    }else{
                        procVariable.setValue(BeanHelper.getProperty(buziVO, boAttrsVO.getCode()));
                    }
                    procVariable.setType(boAttrsVO.getFieldtype());
                }
                variableList.add(procVariable);
            }
            return variableList;
        }else {
            throw new BusinessException("获取单据类型为空，无法完成审批");
        }
    }

    private static void filterFieldType(List<BoAttrsVO> attrsVOS) {
        for(BoAttrsVO attrsVO : attrsVOS) {
            String fieldType = attrsVO.getFieldtype();
            if(FIELD_TYPE_BYTE.equalsIgnoreCase(fieldType)) {
                attrsVO.setFieldtype(RestVariable.BYTE_ARRAY_VARIABLE_TYPE);
            }else if(FIELD_TYPE_CHAR.equalsIgnoreCase(fieldType) ||
                    FIELD_TYPE_VARCHAR.equalsIgnoreCase(fieldType) ||
                    RestVariable.STRING_VARIABLE_TYPE.equalsIgnoreCase(fieldType)) {
                attrsVO.setFieldtype(RestVariable.STRING_VARIABLE_TYPE);
            }else if(FIELD_TYPE_DATETIME.equalsIgnoreCase(fieldType)) {
                attrsVO.setFieldtype(RestVariable.DATE_VARIABLE_TYPE);
            }else if(FIELD_TYPE_INT.equalsIgnoreCase(fieldType) || FIELD_TYPE_INTEGER.equalsIgnoreCase(fieldType) ||
                    FIELD_TYPE_TINYINT.equalsIgnoreCase(fieldType)) {
                attrsVO.setFieldtype(RestVariable.INTEGER_VARIABLE_TYPE);
            }
        }
    }

    public static List<BoAttrsVO> getAttributeVOs(String fileName) throws BusinessException{
        BusinessObjectConfig objectConfig = new BusinessObjectConfig(BusinessObjectConsts.BUSINESS_OBJECT_FILE_PATH, fileName,BillTypeVO.DATA_USAGE_APPROVAL);
        return objectConfig.getBoAttrsVOS();
    }

    @Autowired
    public void setBillTypeQuery(BillTypeQuery billTypeQuery) {
        ProcessVariableProcessor.billTypeQuery = billTypeQuery;
    }

    @Autowired
    public void setProjectSimpleQuery(ProjectSimpleQuery projectSimpleQuery) {
        ProcessVariableProcessor.projectSimpleQuery = projectSimpleQuery;
    }

    public static void addExtendService(String billType, IProcessVariableExtendService extendService){
        variableExtendServiceMap.put(billType, extendService);
    }

    public static void extendVariable(String billType, SuperVO businessVO){
        IProcessVariableExtendService extendService = variableExtendServiceMap.get(billType);
        if(extendService != null){
            try {
                extendService.extendProcessVariable(businessVO);
            } catch (BusinessException e) {
                log.error("业务单据变量值扩展方法执行失败：" + e.getMessage());
            }
        }

    }
}
